/*
 * @文件描述: 
 * @版本: 
 * @作者: 周晨阳
 * @Date: 2021-01-13 23:32:12
 */
#include "CurrentMeter.h"
#include "myADC.h"
/**************以下数值自行定义**************/

//一级放大倍数
#define MAGNIFY_FACTOR 73.5f
//采样电阻大小，单位毫欧
#define SAMPLE_R 5.0f
#define AVR_NUM 400
#define X5_GATE 4
#define X1_GATE 4

//控制引脚 使用PB2
#define CURRENT_GPIO_PIN GPIO_Pin_8
#define CURRENT_GPIO_PORT GPIOC
#define CURRENT_GPIO_CLK RCC_APB2Periph_GPIOC
/**************自定义数值到此完成**************/

/**************变量声明**************/
static unsigned char state;
static float raw_value;
static unsigned char unit;
static float current;
static float AdjCurrent;
static float inputData[AVR_NUM];
static float outputData[20];
//放大器的放大倍数,可以为1 ，5
static int ampFactor = 1;
static uint8_t dataReady = 0;
static int dataPointer = 0;
static double lastCurrent = 0;

/**************函数定义**************/
/**
 * @description: 电流表adc初始化
 * @param {type}
 * @return {type}
 */
static void Current_ADC_Init()
{
#ifndef WIN_SIM
  MultiMeter_ADCx_Init_auto(ADC2, CURRENT_ADC_CHANNEL);

#endif // !WIN_SIM

  ampFactor = 1;
}
/**
 * @description: 电流表初始化
 * @param {type}
 * @return {type}
 */
void CurrentMeterInit()
{

  CurrentADC_GPIO_Init();
  printf("CurrentMeter Init   done...\n");
}
/**
 * @description: adc数值更新的回调函数
 * @param {type}
 * @return {type}
 */
static void AdcInterrupt(int value)
{
  //更新数值
  //MultiMeter_ADC_Stop();
  raw_value = value;
  if (dataPointer < AVR_NUM)
  {
    dataReady = 0;
    inputData[dataPointer] = (float)value;
    dataPointer++;
    //MultiMeter_ADC_Start();
  }
  else
  {
    MultiMeter_ADC_Stop();
    dataReady = 1;
  }

#ifdef ADC_RAW_VALUE
  printf("currentMeter ADC raw :%d \n", value);
#endif
}
/**
 * @description: 打开电流表
 * @param {type}
 * @return {type}
 */
void openCurrentMeter()
{
#ifndef WIN_SIM
  MultiMeter_ADCx_Init_auto(ADC2, CURRENT_ADC_CHANNEL);

#endif // !WIN_SIM

  setCallbackFunc(AdcInterrupt);
  // GPIO_SetBits(CURRENT_GPIO_PORT, CURRENT_GPIO_PIN);
  MultiMeter_ADC_Start();
  state = 1;

#ifdef DEBUG_MODE
  printf("CurrentMeter is open\n");
#endif
}
/**
 * @description: 关闭电流表
 * @param {type}
 * @return {type}
 */
void closeCurrentMeter()
{

  // GPIO_ResetBits(CURRENT_GPIO_PORT, CURRENT_GPIO_PIN);
  MultiMeter_ADC_Stop();
  setCallbackFunc(NULL);
  state = 0;

#ifdef DEBUG_MODE
  printf("CurrentMeter is closed\n");
#endif
}
/**
 * @brief : 获取原始电流值
 * @param {*}
 * @return {*}
 */
float getRawCurrent()
{
  return current;
}
/**
 * @description: 获得调整后的电流
 * @param {type}
 * @return {type}
 */
float getCurrent()
{
  return AdjCurrent;
}
/**
 * @description: 获得实时测量的电流单位
 * @param {type}
 * @return {type}
 */
unsigned char getI_Unit()
{

  if (state)
  {

    if (fabs(current) > 1.0f)
    {
      return UNIT_MA;
    }
    else if (fabs(current) < 1.0f && fabs(current) > 0.001f)
    {
      return UNIT_UA;
    }
    else if (fabs(current) > 1000.0f)
    {
      return UNIT_A;
    }
    else
    {
      return UNIT_MA;
    }
  }
  else
  {
    return 0;
  }
}
/**
 * @brief : 获取电流表指针角度
 * @param {*}
 * @return {*}
 */
float getCurrentNeedleAngle()
{
  float angle = 0;
  if (ampFactor == 1)
  {
    angle = (73.0f / 800.0f) * current;
  }
  else
  {
    angle = (73.0f / 80.0f) * current;
  }
  if (angle > 36.5f)
  {
    angle = 36.5;
  }
  if (angle < -36.5f)
  {
    angle = -36.5f;
  }
  return angle;
}
/**
 * @brief : 
 * @param {int} factor
 * @return {*}
 */
void changeCurrentFactor(int factor) { ampFactor = factor; }
/**
 * @brief : 获取当前放大因数
 * @param {*}
 * @return {*}
 */
int getCurrentFactor() { return ampFactor; }

/**
 * @description: 电流表模块的looper
 * @param {type}
 * @return {type}
 */
void CurrentMeterLooper()
{
  float adjCurrent = 0;
  float adcVoltage = 0;
  double realCurrent = 0;
  int l = 0;
  if (!state && dataReady == 0)
  {
    return;
  }
  dataReady = 0;

#ifndef SIMULATE_VALUE

/*******加入FIR滤波算法滤除高频成分*******/
#ifdef USE_FIR

//对数据进行滤波
//firFilterFloat(inputData, outputData, 20);
#endif
  /**********FIR滤波算法结束************************/

  dataPointer = 0;
  for (l = 0; l < AVR_NUM; l++)
  {
    realCurrent += inputData[l];
  }
  realCurrent /= (float)AVR_NUM;
/***加入限幅滤波算法，防止数字不停抖动*****/
#ifdef ANTI_INTERFERENCE

  if (fabs(realCurrent - lastCurrent) < X1_GATE)
  {
    realCurrent = lastCurrent;
  }
  else
  {
    lastCurrent = realCurrent;
  }
#else
  lastCurrent = realCurrent;
#endif
  /***********限幅滤波算法结束*****/

  printf("raw adc :%d\n", (int)realCurrent);
/************校准程序*******************/
#ifdef USE_CALIBRATION
  //由于电流表存在零漂，现在无法正确通过公式计算出电流，只能直接通过拟合的数据来计算
  if (ampFactor == 1)
  {
    // y = 0.1675762 x - 375.7491844 R² = 0.9999894
#define X1 (0.1675762f)
#define X0 (-375.7491844f)

    //此处计算出来的电流单位是mA
    realCurrent = realCurrent * X1 + X0;
  }
  else
  {
    //y = 0.0330662 x - 99.2200990 R² = 0.9999984
#define X3 (0.0330662f)
#define X2 (-99.2200990f)
    realCurrent = realCurrent * X3 + X2;
  }

#else
  /************end*********************/
#endif
  /************校准结束*******************/
  //给全局变量赋值
  current = realCurrent;

#else
  //测试值
  current = 0.4f;

#endif

#ifdef DEBUG_MODE
//printf("current is :  %f a \n", current);
#endif

  /******自动根据数值大小放大数值***********/
  adjCurrent = fabs(current);
  //mA
  if (adjCurrent > 1.0f)
  {
    adjCurrent = current;
  }
  // uA
  else if (adjCurrent < 1.0f && adjCurrent > 0.001f)
  {
    adjCurrent = current * 1000.0f;
  }
  // A
  else if (adjCurrent > 1000.0f)
  {
    adjCurrent = current / 1000.0f;
  }
  else
  {
  }
  AdjCurrent = adjCurrent;
  MultiMeter_ADC_Start();
}
